package org.dyndns.opendemogroup.optimizer.selections;

import java.util.Random;

import org.dyndns.opendemogroup.optimizer.IOptimizationProblem;
import org.dyndns.opendemogroup.optimizer.ISelection;
import org.dyndns.opendemogroup.optimizer.Member;
import org.dyndns.opendemogroup.optimizer.Pair;
import org.dyndns.opendemogroup.optimizer.Population;

/**
 * <p>
 * A type of selection that was invented in a hurry. It <i>appears</i> to bias
 * high-fitness elements, but I'm not convinced of its efficiency at
 * fitness-proportional selection. The math was inspired by another algorithm:
 * choose, in one pass, a random element out of a sequence whose length is
 * unknown. I found an instance of this here: <a
 * href="http://www.daniweb.com/code/snippet694.html">choose a random element
 * from a sequence of unknown length</a>.
 * </p>
 * <p>
 * It will select a Member at rank <code>i</code> with probability
 * <code>i/n</code>, which means it will be selected, on average,
 * <code>ln(i)</code> times and, as such, it is very elitist.
 * </p>
 */
public class SlidingBias implements ISelection
{

	/**
	 * @see ISelection#select(Random, Population, IOptimizationProblem, int)
	 */
	public Pair<Member, Member> select ( Random randomSource,
			Population population, IOptimizationProblem problem, int loopIndex )
	{
		Pair<Member, Member> result = new Pair<Member, Member> ( );
		boolean maximizing = problem.isMaximizing ( );
		int max = population.getPopulationSize ( ) - 1;

		int one = pick ( randomSource, loopIndex, maximizing, max );
		result.first = population.members[one];

		int two = pick ( randomSource, loopIndex + 1, maximizing, max );
		result.second = population.members[two];
		return result;
	}

	static int pick ( Random randomSource, int loopIndex, boolean maximizing,
			int max )
	{
		int one = randomSource.nextInt ( loopIndex + 1 );
		if ( maximizing )
		{
			one = max - one;
		}
		return one;
	}

	public void reset ( Random randomSource, Population population,
			IOptimizationProblem problem )
	{
		// do nothing on purpose
	}

}
